# 数据库操作
# 以下为数据库操作两个功能的实现。
# 1、执行数据库的增、删、改操作
# 2、执行数据库的查询操作
import sqlite3

# 定义全局变量记录用户名和用户性质，在工具箱标题显示。同时，根据用户是否为管理员，确定用户权限。
# 设定超级用户admin，他永远存在于软件，永不会被删除。
cur_username = ''
password = 0
ifadmin = 1
# 定义全局变量项目名称，项目路径，新建或打开项目后更新，不可以删除当前项目。
cur_proj = ''
cur_path = ''


# 1、执行数据库的增、删、改操作
def exec(sql, values):
    # 连接到SQLite数据库
    # 数据库文件是dp_cmpi.db，如果文件不存在，会自动在当前目录创建
    db = sqlite3.connect("dp_cmpi.db")
    # 创建一个Cursor
    cursor = db.cursor()
    try:
        cursor.execute(sql, values)  # 执行增、删、改的SQL语句
        db.commit()  # 提交数据
        return 1  # 执行成功
    except:
        db.rollback()  # 发生错误时回滚
        return 0  # 执行失败
    finally:
        cursor.close()  # 关闭游标
        db.close()  # 关闭数据库连接


# 2、带参数的查询
def query(sql, *keys):
    # 连接到SQLite数据库
    # 数据库文件是dp_cmpi.db，如果文件不存在，会自动在当前目录创建
    db = sqlite3.connect("dp_cmpi.db")
    # 创建一个Cursor
    cursor = db.cursor()
    try:
        cursor.execute(sql, keys)  # 执行查询的SQL语句
        result = cursor.fetchall()  # 记录查询结果
        return result  # 执行成功
    except:
        db.rollback()  # 发生错误时回滚
        return 0  # 执行失败
    finally:
        cursor.close()  # 关闭游标
        db.close()  # 关闭数据库连接


# 3、查询用户名
def getname(name):
    result = query("select * from user where user = ?", name)
    return len(result)


# 4、查询项目名
def getproj(proj):
    result = query("select * from projinfo where proj=?", proj)
    return len(result)


def is_number(input_str):
    """
    验证输入字符串是否为数字（包括整数和小数）。

    Args:
        input_str (str): 待验证的字符串。

    Returns:
        bool: 如果输入字符串为数字（包括整数和小数），返回 True；否则返回 False。
    """
    # 移除字符串中的正负号（不影响小数判断）
    input_str = input_str.strip("+-")

    # 使用 replace 方法移除所有小数点，检查剩余部分是否全为数字字符
    no_decimal_str = input_str.replace(".", "")
    if not no_decimal_str.isdigit():
        return False

    # 检查原字符串中小数点数量不超过 1 个（防止如 "123.45." 这样的无效输入）
    decimal_count = input_str.count(".")
    if decimal_count > 1:
        return False

    return True


def write_to_csv(file_path, data):
    import os, csv
    """
    将数据写入CSV文件。
    :param file_path: 字符串，指定要写入数据的 CSV 文件的路径。
    :param data: 一个列表，每个元素都是一个表示行数据的列表。
                  如果数据为空，函数不会进行写入操作。
    """
    try:
        if os.path.exists(file_path):
            with open(file_path, 'a', newline='',encoding='utf-8') as csvfile:
                csvwriter = csv.writer(csvfile)
                # 写入一行或多行数据
                for row in data:
                    if isinstance(row, (list, tuple)):  # 确保每一项是可迭代类型
                        csvwriter.writerow(row)
                    else:
                        print(f"忽略非法行数据: {row} (应为可迭代类型)")
    except FileNotFoundError:
        print(f"文件路径不存在: {file_path}")
    except PermissionError:
        print(f"没有足够的权限写入文件: {file_path}")
    except Exception as e:
        print(f"文件操作失败: {e}")


def read_column_csv(file_path, column_name):
    import csv
    """
    使用csv模块从CSV文件中读取指定列的数据。

    :param file_path: CSV文件的路径。
    :param column_name: 要读取列的名称（假设第一行为表头）。
    :return: 一个包含指定列所有数据的列表。
    """
    column_data = []

    with open(file_path, 'r', newline='',encoding='utf-8') as csvfile:
        reader = csv.DictReader(csvfile)

        for row in reader:
            if column_name in row:
                column_data.append(row[column_name])
            else:
                print(f"警告：在行中未找到列名'{column_name}'，跳过该行")

    return column_data


def remove_rows_with_content(file_path, column_name, target_content, output_file=None):
    import csv
    """
    从CSV文件中删除包含特定内容的行，并可选择性保存到新的CSV文件。

    参数:
    file_path (str): 输入CSV文件的路径。
    column_name (str): 包含目标内容的列名。
    target_content (str): 要删除的行中必须包含的特定内容。
    output_file (str, optional): 输出CSV文件的路径。如果不提供，将不会保存到文件。

    返回:
    list[list]: 处理后的数据（不含指定内容的行），以二维列表形式表示。
    """

    # 初始化结果列表和字段名列表
    result_data = []
    fieldnames = []

    # 读取CSV文件
    with open(file_path, newline='',encoding='utf-8') as csvfile:
        reader = csv.DictReader(csvfile)
        fieldnames = reader.fieldnames

        # 遍历每一行
        for row in reader:
            if row[column_name] != target_content:
                result_data.append([row[field] for field in fieldnames])

    try:
        # 决定保存位置：提供output_file时保存至新文件，否则覆盖原文件
        if output_file is not None:
            save_path = output_file
        else:
            save_path = file_path

        # 将处理后的数据保存到指定文件
        with open(save_path, 'w', newline='',encoding='utf-8') as output_csvfile:
            writer = csv.writer(output_csvfile)
            writer.writerow(fieldnames)
            writer.writerows(result_data)
    except Exception as e:
        print(f"Error writing to output file: {e}")


def rewrite_csv_first_column_indices(csv_file_path):
    import csv
    # 读取CSV文件内容
    with open(csv_file_path, 'r', newline='',encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile)
        header = next(reader)  # 跳过第一行（标题行）

        # 将修改后的数据写回原文件
        with open(csv_file_path, 'w', newline='',encoding='utf-8') as outfile:
            writer = csv.writer(outfile)

            # 写入原始标题行
            writer.writerow(header)

            # 对于数据行（从第二行开始），重新计算第一列序号并写入
            for i, row in enumerate(reader, start=1):
                row[0] = str(i)  # 更新第一列序号
                writer.writerow(row)


def csv_to_excel(csv_file_path, excel_file_path):
    import pandas as pd
    """
    将指定CSV文件转换为Excel文件。

    :param csv_file_path: CSV文件的路径。
    :param excel_file_path: 输出Excel文件的路径。
    """
    # 读取CSV文件
    df = pd.read_csv(csv_file_path, encoding='utf-8')

    # 导出为Excel文件
    df.to_excel(excel_file_path, index=False)


def merge_same_content_cells(input_file, col_index, start_row=1):
    from openpyxl import load_workbook
    from openpyxl.utils import get_column_letter
    """
    合并Excel中某一列中内容相同的单元格。1、2、3、15、16、17列，桩号，里程，龄期，上下得分，综合得分，综合评定

    :param input_file: 输入的Excel文件路径。
    :param col_index: 待合并列的索引（从0开始计数）。
    :param start_row: 开始检查合并的起始行，默认为1（即忽略表头）。
    
    """
    # 加载输入的Excel文件
    wb = load_workbook(input_file)
    ws = wb.active

    # 获取待合并列的列字母（例如，第1列为'A'）
    col_letter = get_column_letter(col_index + 1)

    # 定义一个合并范围列表，存储需要合并的单元格范围，二维数组，包含所有合并范围【行开始索引，行结束索引】
    merge_ranges = []

    # 遍历待合并列
    for i in range(start_row + 1, ws.max_row + 1):  # 从start_row+1行开始
        current_val = ws[f"{col_letter}{i}"].value
        previous_val = ws[f"{col_letter}{i - 1}"].value

        # 如果当前值与前一行相同，则合并这两个单元格
        if current_val == previous_val:
            if not merge_ranges or merge_ranges[-1][1] != i - 1:
                merge_ranges.append([i - 1, i])  # 新建一个合并范围
            else:
                merge_ranges[-1][1] += 1  # 扩展当前合并范围
        else:
            if merge_ranges and merge_ranges[-1][1] == i - 1:
                # 上一个合并范围结束，记录此次合并
                merge_range_str = f"A{merge_ranges[-1][0]}:A{merge_ranges[-1][1]}"
                ws.merge_cells(merge_range_str)
                merge_range_str = f"{col_letter}{merge_ranges[-1][0]}:{col_letter}{merge_ranges[-1][1]}"
                ws.merge_cells(merge_range_str)
                merge_range_str = f"C{merge_ranges[-1][0]}:C{merge_ranges[-1][1]}"
                ws.merge_cells(merge_range_str)
                merge_range_str = f"P{merge_ranges[-1][0]}:P{merge_ranges[-1][1]}"
                ws.merge_cells(merge_range_str)
                merge_range_str = f"Q{merge_ranges[-1][0]}:Q{merge_ranges[-1][1]}"
                ws.merge_cells(merge_range_str)
                merge_range_str = f"R{merge_ranges[-1][0]}:R{merge_ranges[-1][1]}"
                ws.merge_cells(merge_range_str)

    # 处理最后一个可能存在的合并范围
    if merge_ranges and merge_ranges[-1][1] == ws.max_row:
        merge_range_str = f"A{merge_ranges[-1][0]}:A{merge_ranges[-1][1]}"
        ws.merge_cells(merge_range_str)
        merge_range_str = f"{col_letter}{merge_ranges[-1][0]}:{col_letter}{merge_ranges[-1][1]}"
        ws.merge_cells(merge_range_str)
        merge_range_str = f"C{merge_ranges[-1][0]}:C{merge_ranges[-1][1]}"
        ws.merge_cells(merge_range_str)
        merge_range_str = f"P{merge_ranges[-1][0]}:P{merge_ranges[-1][1]}"
        ws.merge_cells(merge_range_str)
        merge_range_str = f"Q{merge_ranges[-1][0]}:Q{merge_ranges[-1][1]}"
        ws.merge_cells(merge_range_str)
        merge_range_str = f"R{merge_ranges[-1][0]}:R{merge_ranges[-1][1]}"
        ws.merge_cells(merge_range_str)

    # 保存合并后的结果到输出文件
    wb.save(input_file)


def merge_down_empty_cells(input_file, col_index, start_row=1):
    from openpyxl import load_workbook
    from openpyxl.utils import get_column_letter
    """
    合并Excel某一列中不为空的单元格与其下面的连续空单元格。

    :param input_file: 输入的Excel文件路径。
    :param output_file: 输出的Excel文件路径（合并后结果）。
    :param col_index: 待处理列的索引（从0开始计数）。
    :param start_row: 开始检查合并的起始行，默认为1（即忽略表头）。
    """
    # 加载输入的Excel文件
    wb = load_workbook(input_file)
    ws = wb.active

    # 获取待处理列的列字母（例如，第1列为'A'）
    col_letter = get_column_letter(col_index + 1)

    # 遍历待处理列
    last_nonempty_row = start_row - 1  # 初始化为无效值，用于标记上一个非空单元格的位置
    for i in range(start_row, ws.max_row + 1):  # 从start_row行开始
        cell_value = ws[f"{col_letter}{i}"].value

        if cell_value is not None:  # 当前单元格非空
            if i > last_nonempty_row + 1:  # 与上一个非空单元格之间有空单元格
                merge_range_str = f"{col_letter}{last_nonempty_row + 1}:{col_letter}{i - 1}"
                ws.merge_cells(merge_range_str)

            last_nonempty_row = i

    # 保存合并后的结果到输出文件
    wb.save(input_file)
